package com.unlcn.ils.wms.backend.service.inbound.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.unlcn.ils.wms.backend.enums.*;
import com.unlcn.ils.wms.backend.service.inbound.Wms2MesInboundNoticeService;
import com.unlcn.ils.wms.backend.util.DateUtils;
import com.unlcn.ils.wms.backend.util.GenerateFlowCodeUtils;
import com.unlcn.ils.wms.backend.util.SnowflakeIdWorker;
import com.unlcn.ils.wms.base.dto.Wms2MesInboundServiceParamDTO;
import com.unlcn.ils.wms.base.dto.WmsWarehouseNoticeDetailDTOForSchedule;
import com.unlcn.ils.wms.base.dto.WmsWarehouseNoticeHeadDTO;
import com.unlcn.ils.wms.base.mapper.extmapper.WmsWarehouseNoticeExtMapper;
import com.unlcn.ils.wms.base.mapper.inbound.WmsWarehouseNoticeHeadMapper;
import com.unlcn.ils.wms.base.mapper.junmadcs.WmsSapLogMapper;
import com.unlcn.ils.wms.base.model.inbound.WmsWarehouseNoticeDetail;
import com.unlcn.ils.wms.base.model.inbound.WmsWarehouseNoticeHead;
import com.unlcn.ils.wms.base.model.inbound.WmsWarehouseNoticeHeadExample;
import com.unlcn.ils.wms.base.model.junmadcs.WmsSapLogWithBLOBs;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Service
public class Wms2MesInboundNoticeServiceImpl implements Wms2MesInboundNoticeService {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private WmsSapLogMapper wmsSapLogMapper;
    @Autowired
    private WmsWarehouseNoticeExtMapper wmsWarehouseNoticeExtMapper;
    @Autowired
    private WmsWarehouseNoticeHeadMapper wmsWarehouseNoticeHeadMapper;


    @Override
    public HashMap<String, Object> updateInboundDataFromMes(Wms2MesInboundServiceParamDTO[] paramDTOS) {
        if (logger.isInfoEnabled()) {
            logger.info("Wms2MesInboundNoticeServiceImpl.updateInboundDataFromMes params{} service start:");
        }
        insertInterfaceLog(paramDTOS);

        HashMap<String, Object> resultMap = Maps.newHashMap();
        if (paramDTOS == null || paramDTOS.length < 1) {
            resultMap.put("success", "E");
            resultMap.put("message", "传入参数不能为空!");
            resultMap.put("messageDetail", "");
            return resultMap;
        }
        //数据完整性校验
        StringBuilder message = new StringBuilder();
        ArrayList<String> vinList = Lists.newArrayList();

        checkParamDTO(paramDTOS, message, vinList);
        if (StringUtils.isNotBlank(message)) {
            resultMap.put("success", "E");
            resultMap.put("message", message.toString());
            resultMap.put("messageDetail", "");
            return resultMap;
        }
        HashMap<String, Object> params = Maps.newHashMap();
        params.put("notDel", DeleteFlagEnum.NORMAL.getValue());
        params.put("z1Type", InboundOrderBusinessTypeEnum.Z1.getCode());
        params.put("whCode", WhCodeEnum.JM_XY.getValue());
        params.put("vinList", vinList);
        //校验重复性
        List<WmsWarehouseNoticeHeadDTO> hasInsertVin = wmsWarehouseNoticeExtMapper.selectWmsWarehouseNoticeListByVinList(params);
        StringBuilder messageDetail = new StringBuilder();
        ArrayList<Object> insertedVin = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(hasInsertVin)) {
            for (WmsWarehouseNoticeHeadDTO head : hasInsertVin) {
                WmsWarehouseNoticeDetailDTOForSchedule detail = head.getDetailList().get(0);
                if (detail != null && StringUtils.isNotBlank(detail.getWndVin())) {
                    insertedVin.add(detail.getWndVin());
                    messageDetail.append(detail.getWndVin()).append(",");
                }
            }
            messageDetail.append("已经存在于WMS系统");
        }
        ArrayList<WmsWarehouseNoticeHead> insertHeads = Lists.newArrayList();
        ArrayList<WmsWarehouseNoticeDetail> insertDetails = Lists.newArrayList();
        SnowflakeIdWorker idWorker = new SnowflakeIdWorker(31L, 31L);
        //查上一次的批次号
        WmsWarehouseNoticeHeadExample headExample = new WmsWarehouseNoticeHeadExample();
        headExample.createCriteria().andWnhBatchNoIsNotNull();
        headExample.setOrderByClause("wnh_id desc");
        headExample.setLimitStart(0);
        headExample.setLimitEnd(1);
        List<WmsWarehouseNoticeHead> noticeHeads = wmsWarehouseNoticeHeadMapper.selectByExample(headExample);
        HashMap<String, String> lastFlowCodeMap = Maps.newHashMap();
        //设置批次号
        String atBatchNo;
        //设置流水号
        String flowCode;
        if (CollectionUtils.isNotEmpty(noticeHeads)) {
            atBatchNo = noticeHeads.get(0).getWnhBatchNo();
            flowCode = noticeHeads.get(0).getWnhUnlcnOrderNo();
            atBatchNo = GenerateFlowCodeUtils.getnumber("BTN", atBatchNo, "0000");
            lastFlowCodeMap.put("LAST_CODE", flowCode);
        } else {
            atBatchNo = GenerateFlowCodeUtils.getnumber("BTN", null, "0000");
            lastFlowCodeMap.put("LAST_CODE", null);
        }
        for (Wms2MesInboundServiceParamDTO dto : paramDTOS) {
            if (CollectionUtils.isNotEmpty(insertedVin) && insertedVin.contains(dto.getVin())) {
                //如果已经插入
                continue;
            }
            WmsWarehouseNoticeHead head = new WmsWarehouseNoticeHead();
            WmsWarehouseNoticeDetail detail = new WmsWarehouseNoticeDetail();
            //补全其他字段 -detail
            detail.setWndVin(dto.getVin());
            detail.setWndMaterialCode(dto.getMaterialCode());
            detail.setWndMaterialName(dto.getMaterialName());
            detail.setWndColorCode(dto.getColorCode());
            detail.setWndColorName(dto.getColorName());
            detail.setWndProducteTime(DateUtils.StrToDate(dto.getProduceTime(), DateUtils.FORMAT_DATETIME));
            detail.setWndOfflineTime(DateUtils.StrToDate(dto.getOfflineTime(), DateUtils.FORMAT_DATETIME));
            detail.setWndEngineNo(dto.getEngineNo());
            detail.setWndCertification(dto.getCertification());
            detail.setWndGearBoxNo(dto.getGearBoxNo());
            detail.setWndVehicleCode(dto.getVehicleCode());
            detail.setWndVehicleName(dto.getVehicleName());
            detail.setWndVehicleDesc(dto.getVehicleDesc());
            detail.setWndBusinessType(dto.getBusinessType());
            String whCode = " ";
            if (StringUtils.isNotBlank(dto.getWarehouseCode()) && dto.getWarehouseCode().contains("XY")) {
                whCode = WhCodeEnum.JM_XY.getValue();
            }
            detail.setWndWarehouseCode(whCode);
            detail.setWndCreate(new Date());
            detail.setWndUpdate(new Date());
            detail.setWndSendBusinessFlag(String.valueOf(SendBusinessFlagEnum.SEND_N.getValue()));
            detail.setWndBusinessStatus(WmsBusinessStatusEnum.WND_NOT_RECEIVE.getCode());
            detail.setWndDataStatus(String.valueOf(DeleteFlagEnum.NORMAL.getValue()));
            detail.setWndTransferFlag(WmsInboundOrderStockTransferEnum.STOCK_NORMAL.getCode());
            //head
            head.setWnhId(idWorker.nextId());
            head.setWnhCustomerCode(WmsCustomerEnum.JM.getCode());
            head.setWnhCustomerName(WmsCustomerEnum.JM.getName());
            head.setWnhDataStatus(String.valueOf(DeleteFlagEnum.NORMAL.getValue()));
            head.setWnhBusinessStatus(WmsBusinessStatusEnum.WNH_NOT_INBOUND.getCode());
            head.setWnhSysSource(WmsSysSourceEnum.MES_INTERFACE.getValue());
            head.setWnhBatchNo(atBatchNo);
            head.setWnhDataTimestamp(Long.valueOf(DateUtils.getStringFromDate(new Date(), DateUtils.FORMAT_DATETIME_NO_SEPARATOR)));
            head.setWnhCreate(new Date());
            head.setWnhUpdate(new Date());
            head.setWnhInboundNum(1);
            head.setWnhWarehouseCode(whCode);
            head.setWnhCreateUserName(WmsSysSourceEnum.MES_INTERFACE.getValue());
            head.setWnhUpdateUserName(WmsSysSourceEnum.MES_INTERFACE.getValue());
            detail.setWndCreateUserName(WmsSysSourceEnum.MES_INTERFACE.getValue());
            detail.setWndUpdateUserName(WmsSysSourceEnum.MES_INTERFACE.getValue());
            //设置head订单流水号
            String last_code = lastFlowCodeMap.get("LAST_CODE");
            String curr_code;
            if (StringUtils.isBlank(last_code)) {
                curr_code = GenerateFlowCodeUtils.getnumber("ASN", null, "0000");
                lastFlowCodeMap.put("LAST_CODE", curr_code);
            } else {
                curr_code = GenerateFlowCodeUtils.getnumber("ASN", last_code, "0000");
                lastFlowCodeMap.put("LAST_CODE", curr_code);
            }
            head.setWnhUnlcnOrderNo(curr_code);
            //detail关联
            detail.setWndHeadId(head.getWnhId());
            //批量写入
            insertHeads.add(head);
            insertDetails.add(detail);

        }
        if (CollectionUtils.isNotEmpty(insertDetails) && CollectionUtils.isNotEmpty(insertHeads)) {
            wmsWarehouseNoticeExtMapper.insertHeadBatch(insertHeads);
            wmsWarehouseNoticeExtMapper.insertDetailBatch(insertDetails);
        }
        resultMap.put("success", "S");
        resultMap.put("messageDetail", messageDetail.toString());
        resultMap.put("message", "操作成功");
        return resultMap;

    }

    /**
     * 插入日志
     *
     * @param paramDTOS 接口参数
     */
    private void insertInterfaceLog(Wms2MesInboundServiceParamDTO[] paramDTOS) {
        new Thread(() -> {
            WmsSapLogWithBLOBs log = new WmsSapLogWithBLOBs();
            log.setMsgBody(WmsSysSourceEnum.MES_INTERFACE.getValue());
            log.setGmtCreate(new Date());
            log.setGmtUpdate(new Date());
            log.setUrl("Wms2MesInboundNoticeServiceImpl.updateInboundDataFromMes");
            log.setSendType(WmsGateControllerTypeEnum.GATE_IN.getCode());
            log.setParam(JSONObject.toJSONString(paramDTOS));
            wmsSapLogMapper.insertSelective(log);
        }).start();
    }

    /**
     * 参数完整性校验
     *
     * @param paramDTOS 参数封装
     * @param message   错误消息
     * @param vinList   通过校验的车架号
     */
    private void checkParamDTO(Wms2MesInboundServiceParamDTO[] paramDTOS, StringBuilder message, ArrayList<String> vinList) {
        for (int i = 0; i < paramDTOS.length; i++) {
            Wms2MesInboundServiceParamDTO dto = paramDTOS[i];
            if (StringUtils.isBlank(dto.getVin())) {
                message.append("第").append(i + 1).append("行数据,车架号为空!");
            }
            if (StringUtils.isBlank(dto.getMaterialCode())) {
                message.append("第").append(i + 1).append("行数据,物料编码为空!");
            }
            if (StringUtils.isBlank(dto.getMaterialName())) {
                message.append("第").append(i + 1).append("行数据,物料名称为空!");
            }
            if (StringUtils.isBlank(dto.getColorCode())) {
                message.append("第").append(i + 1).append("行数据,颜色编码为空!");
            }
            if (StringUtils.isBlank(dto.getColorName())) {
                message.append("第").append(i + 1).append("行数据,颜色名称为空!");
            }
            if (StringUtils.isBlank(dto.getProduceTime())) {
                message.append("第").append(i + 1).append("行数据,生产时间为空!");
            }
            if (StringUtils.isBlank(dto.getOfflineTime())) {
                message.append("第").append(i + 1).append("行数据,下线时间为空!");
            }
            if (StringUtils.isBlank(dto.getVehicleCode())) {
                message.append("第").append(i + 1).append("行数据,车型编码为空!");
            }
            if (StringUtils.isBlank(dto.getVehicleName())) {
                message.append("第").append(i + 1).append("行数据,车型名称为空!");
            }
            if (StringUtils.isBlank(dto.getVehicleDesc())) {
                message.append("第").append(i + 1).append("行数据,车型描述为空!");
            }
            if (StringUtils.isBlank(dto.getBusinessType())) {
                message.append("第").append(i + 1).append("行数据,业务类型为空!");
            }
            if (StringUtils.isBlank(dto.getWarehouseCode())) {
                message.append("第").append(i + 1).append("行数据,仓库code为空!");
            }
            if (!(StringUtils.isNotBlank(dto.getWarehouseCode()) &&
                    WhCodeEnum.XY01.getValue().equals(dto.getWarehouseCode()))) {
                message.append("第").append(i + 1).append("行数据,仓库code不支持!");
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                if (StringUtils.isNotBlank(dto.getProduceTime())) {
                    sdf.parse(dto.getProduceTime());
                }
            } catch (Exception e) {
                message.append("第").append(i + 1).append("行数据,生产日期格式不正确:(yyyy-MM-dd HH:mm:ss)!");
            }
            try {
                if (StringUtils.isNotBlank(dto.getOfflineTime())) {
                    sdf.parse(dto.getOfflineTime());
                }
            } catch (Exception e) {
                message.append("第").append(i + 1).append("行数据,下线日期格式不正确:(yyyy-MM-dd HH:mm:ss)!");
            }
            if (StringUtils.isBlank(message)) {
                vinList.add(dto.getVin());
            }
        }
    }
}
